package zelix.hack.hacks;

import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.inventory.GuiChest;
import net.minecraft.client.gui.inventory.GuiInventory;
import zelix.hack.Hack;
import zelix.hack.HackCategory;
import zelix.utils.*;
import zelix.utils.ReflectionHelper;
import zelix.utils.TimerUtils;
import zelix.utils.Utils;
import zelix.utils.Wrapper;
import zelix.value.BooleanValue;
import zelix.value.Mode;
import zelix.value.ModeValue;
import zelix.value.NumberValue;
import net.minecraft.block.material.Material;
import net.minecraft.client.Minecraft;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import org.lwjgl.input.Mouse;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class AutoClicker extends Hack {

    TimerUtils time = new TimerUtils();

    int delay;
    static ModeValue mode;
    static BooleanValue OnClick,inventoryFill,weaponOnly;
    static NumberValue CPS,RandomMS;

    public AutoClicker() {
        super("AutoClicker", HackCategory.COMBAT);

        mode = new ModeValue("Mode", new Mode("Left", true
        ), new Mode("Right", false), new Mode("Both", false));
        OnClick = new BooleanValue("OnClick", true);
        inventoryFill = new BooleanValue("InvFill", true);
        weaponOnly = new BooleanValue("Weapon", true);
        //External = new BooleanValue("External", false);
        CPS = new NumberValue("CPS", 9.0D, 1.0D, 20.0D);
        RandomMS = new NumberValue("RandomMS", 5.0D, 0.0D, 250.0D);

        addValue(mode,OnClick,inventoryFill,weaponOnly,CPS,RandomMS);

    }


    @Override
    public void onClientTick(TickEvent.ClientTickEvent event) {

        if (this.time.isDelay(delay)) {
            if (OnClick.getValue()) {
                if(mode.getMode("Left").isToggled()) {
                    if (Mouse.isButtonDown(0)) {
                        this.click();
                    }
                } else if(mode.getMode("Right").isToggled()){
                    if (Mouse.isButtonDown(1)) {
                        this.click();
                    }
                } else{
                    if (Mouse.isButtonDown(1) || Mouse.isButtonDown(0)) {
                        this.click();
                    }
                }
            } else {
                this.click();
            }
        }
    }

    private void click() {
;
        delay = (int) Math.round(1000 / CPS.getValue());
        int random = (int) (Math.random() * RandomMS.getValue());
        delay = delay + random;
        this.time.setLastMS();

        if(mode.getMode("Left").isToggled()) {
            clickMouse();
        } else if(mode.getMode("Right").isToggled()){
            rightClickMouse();
        } else{
            if (Mouse.isButtonDown(0)) {
                clickMouse();
            }
            if (Mouse.isButtonDown(1)) {
                rightClickMouse();
            }
        }
        //Wrapper.INSTANCE.mc().playerController.attackEntity(Wrapper.INSTANCE.mc().thePlayer, Wrapper.INSTANCE.mc().objectMouseOver.entityHit);
    }

    public void doInventoryClick(){
        if (inventoryFill.getValue() && (Wrapper.INSTANCE.mc().currentScreen instanceof GuiInventory || Wrapper.INSTANCE.mc().currentScreen instanceof GuiChest)) {
            this.inInvClick(Wrapper.INSTANCE.mc().currentScreen);
        }
    }

    private Method playerMouseInput = ReflectionHelper.findMethod(
            GuiScreen.class,
            null,
            new String[]{
                    "func_73864_a",
                    "mouseClicked"
            },
            Integer.TYPE,
            Integer.TYPE,
            Integer.TYPE
    );;

    private void inInvClick(GuiScreen guiScreen) {
        int mouseInGUIPosX = Mouse.getX() * guiScreen.width / Wrapper.INSTANCE.mc().displayWidth;
        int mouseInGUIPosY = guiScreen.height - Mouse.getY() * guiScreen.height / Wrapper.INSTANCE.mc().displayHeight - 1;

        try {
            this.playerMouseInput.invoke(guiScreen, mouseInGUIPosX, mouseInGUIPosY, 0);
        } catch (IllegalAccessException | InvocationTargetException var5) {
        }

    }

    private void clickMouse()
    {
        if(Wrapper.INSTANCE.mc().currentScreen!= null || !Wrapper.INSTANCE.mc().inGameHasFocus) {
            doInventoryClick();
            return;
        }
        if (weaponOnly.getValue() && !Utils.isPlayerHoldingWeapon()) {
            return;
        }

        int leftClickCounter = 0;
        Minecraft mc =Minecraft.getMinecraft();

        if (leftClickCounter <= 0)
        {
            if (Minecraft.getMinecraft().objectMouseOver == null) {}
            else if (!Wrapper.INSTANCE.mc().player.isRowingBoat())
            {
                switch (Wrapper.INSTANCE.mc().objectMouseOver.typeOfHit)
                {
                    case ENTITY:
                        Wrapper.INSTANCE.mc().playerController.attackEntity(Wrapper.INSTANCE.mc().player, Wrapper.INSTANCE.mc().objectMouseOver.entityHit);
                        break;
                    case BLOCK:
                        BlockPos blockpos = Wrapper.INSTANCE.mc().objectMouseOver.getBlockPos();

                        if (!Wrapper.INSTANCE.mc().world.isAirBlock(blockpos))
                        {
                            Wrapper.INSTANCE.mc().playerController.clickBlock(blockpos, Wrapper.INSTANCE.mc().objectMouseOver.sideHit);
                            break;
                        }

                    case MISS:
                        Wrapper.INSTANCE.mc().player.resetCooldown();
                        net.minecraftforge.common.ForgeHooks.onEmptyLeftClick(Wrapper.INSTANCE.mc().player);
                }

                Wrapper.INSTANCE.mc().player.swingArm(EnumHand.MAIN_HAND);
            }
        }

    }

    public static void rightClickMouse()
    {

        Minecraft mc =Minecraft.getMinecraft();
        if (!Wrapper.INSTANCE.mc().playerController.getIsHittingBlock())
        {
            if (!Wrapper.INSTANCE.mc().player.isRowingBoat())
            {
                if (Wrapper.INSTANCE.mc().objectMouseOver == null)
                {
                    //LOGGER.warn("Null returned as 'hitResult', this shouldn't happen!");
                }

                for (EnumHand enumhand : EnumHand.values())
                {
                    ItemStack itemstack = Wrapper.INSTANCE.mc().player.getHeldItem(enumhand);

                    if (Wrapper.INSTANCE.mc().objectMouseOver != null)
                    {
                        switch (Wrapper.INSTANCE.mc().objectMouseOver.typeOfHit)
                        {
                            case ENTITY:

                                if (Wrapper.INSTANCE.mc().playerController.interactWithEntity(Wrapper.INSTANCE.mc().player, Wrapper.INSTANCE.mc().objectMouseOver.entityHit, Wrapper.INSTANCE.mc().objectMouseOver, enumhand) == EnumActionResult.SUCCESS)
                                {
                                    return;
                                }

                                if (Wrapper.INSTANCE.mc().playerController.interactWithEntity(Wrapper.INSTANCE.mc().player, Wrapper.INSTANCE.mc().objectMouseOver.entityHit, enumhand) == EnumActionResult.SUCCESS)
                                {
                                    return;
                                }

                                break;
                            case BLOCK:
                                BlockPos blockpos = Wrapper.INSTANCE.mc().objectMouseOver.getBlockPos();

                                if (Wrapper.INSTANCE.mc().world.getBlockState(blockpos).getMaterial() != Material.AIR)
                                {
                                    int i = itemstack.getCount();
                                    EnumActionResult enumactionresult = Wrapper.INSTANCE.mc().playerController.processRightClickBlock(Wrapper.INSTANCE.mc().player, Wrapper.INSTANCE.mc().world, blockpos, Wrapper.INSTANCE.mc().objectMouseOver.sideHit, Wrapper.INSTANCE.mc().objectMouseOver.hitVec, enumhand);

                                    if (enumactionresult == EnumActionResult.SUCCESS)
                                    {
                                        Wrapper.INSTANCE.mc().player.swingArm(enumhand);

                                        if (!itemstack.isEmpty() && (itemstack.getCount() != i || Wrapper.INSTANCE.mc().playerController.isInCreativeMode()))
                                        {
                                            Wrapper.INSTANCE.mc().entityRenderer.itemRenderer.resetEquippedProgress(enumhand);
                                        }

                                        return;
                                    }
                                }
                        }
                    }

                    if (itemstack.isEmpty() && (Wrapper.INSTANCE.mc().objectMouseOver == null || Wrapper.INSTANCE.mc().objectMouseOver.typeOfHit == RayTraceResult.Type.MISS)) net.minecraftforge.common.ForgeHooks.onEmptyClick(Wrapper.INSTANCE.mc().player, enumhand);
                    if (!itemstack.isEmpty() && Wrapper.INSTANCE.mc().playerController.processRightClick(Wrapper.INSTANCE.mc().player, Wrapper.INSTANCE.mc().world, enumhand) == EnumActionResult.SUCCESS)
                    {
                        Wrapper.INSTANCE.mc().entityRenderer.itemRenderer.resetEquippedProgress(enumhand);
                        return;
                    }
                }
            }
        }
    }

}
